package icu.d4peng.basic.http.feign.clientconfig;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

import javax.annotation.PreDestroy;

import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.commons.httpclient.OkHttpClientConnectionPoolFactory;
import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
import icu.d4peng.basic.http.feign.support.FeignHttpClientProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author d4peng d4peng@qq.com
 * @date 2023-11-26 15:36:16
 */

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(OkHttpClient.class)
public class OkHttpFeignConfiguration {

	private OkHttpClient okHttpClient;

	@Bean
	@ConditionalOnMissingBean(ConnectionPool.class)
	public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties,
			OkHttpClientConnectionPoolFactory connectionPoolFactory) {
		int maxTotalConnections = httpClientProperties.getMaxConnections();
		long timeToLive = httpClientProperties.getTimeToLive();
		TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
		return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit);
	}

	@Bean
	public OkHttpClient client(OkHttpClientFactory httpClientFactory, ConnectionPool connectionPool,
			FeignHttpClientProperties httpClientProperties) {
		boolean followRedirects = httpClientProperties.isFollowRedirects();
		int connectTimeout = httpClientProperties.getConnectionTimeout();
		Duration reaTimeout = httpClientProperties.getOkHttp().getReadTimeout();
		this.okHttpClient = httpClientFactory.createBuilder(httpClientProperties.isDisableSslValidation())
			.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
			.followRedirects(followRedirects)
			.readTimeout(reaTimeout)
			.connectionPool(connectionPool)
			.build();
		return this.okHttpClient;
	}

	@PreDestroy
	public void destroy() {
		if (this.okHttpClient != null) {
			this.okHttpClient.dispatcher().executorService().shutdown();
			this.okHttpClient.connectionPool().evictAll();
		}
	}

}
